﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProBugTracker.Core.Interface;
using ProBugTracker.Domain;
using ProBugTracker.Data;
using ProBugTracker.Data.Interface;
using System.Transactions;

namespace ProBugTracker.Core
{
    public class UserManager : IUserManager
    {
        private IUserManagerData _userManagerData;
        private IPermissionManagerData _permissionManagerData;
        private IRoleManager _roleManager;

        public UserManager(IUserManagerData userManagerData, IPermissionManagerData permissionManagerData, IRoleManager roleManager)
        {
            this._userManagerData = userManagerData;
            this._permissionManagerData = permissionManagerData;
            this._roleManager = roleManager;
        }

        public bool AddNewUser(User user)
        {
            try
            {
                if (user != null)
                {
                    using (TransactionScope scope = new TransactionScope())
                    {
                        UserDB userInfo = new UserDB()
                        {
                            FirstName = user.FirstName,
                            MiddleName = user.MiddleName,
                            LastName = user.LastName,
                            UserName = user.UserName,
                            Password = user.Password,
                            LastChangeDate = DateTime.Now,
                            Active = true,
                            Email = user.Email
                        };
                        //Add New User
                        userInfo = _userManagerData.AddNewUser(userInfo);

                        //Add User Role
                        foreach (UserAssignRole userAssignRole in user.Role)
                        {
                            UserAssignRoleDB userAssignRoleDB = new UserAssignRoleDB()
                            {
                                UserID=userInfo.ID,
                                UserRoleID = userAssignRole.UserRoleID,
                                StartDate = userAssignRole.Startdate,
                                EndDate = userAssignRole.EndDate,
                                Active=true
                            };
                            userAssignRoleDB = _userManagerData.AddNewUserRole(userAssignRoleDB);

                            //Add User Role Permission
                            foreach (RoleAssignPermission roleAssignPermission in userAssignRole.PermissionLevel)
                            {
                                RoleAssignPermissionDB roleAssignPermissionDB = new RoleAssignPermissionDB()
                                {
                                    UserRoleID = userAssignRoleDB.UserRoleID,
                                    UserPermissionID = userInfo.ID,
                                    PermissionStartDate = roleAssignPermission.PermissionStartDate,
                                    PermissionEndDate=roleAssignPermission.PermissionEndDate,
                                    Active=true
                                };

                                roleAssignPermissionDB = _permissionManagerData.AddRolePermission(roleAssignPermissionDB);
                            }

                        }
                        
                        scope.Complete();
                        return true;
                    }
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool EditNewUser(User user)
        {
            try
            {
                if (user != null)
                {
                    UserDB userInfor = new UserDB()
                    {
                        ID = user.UserID,
                        FirstName = user.FirstName,
                        MiddleName = user.MiddleName,
                        LastName = user.LastName,
                        Email = user.Email,
                        LastChangeDate = DateTime.Now
                    };

                    return _userManagerData.EditNewUser(userInfor);
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool DeleteUser(int userID)
        {
            try
            {
                return _userManagerData.DeleteUser(userID);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool AddNewUserRole(int userID, int roleID, DateTime startDate, DateTime endDate)
        {
            try
            {
                if (userID > 0 && roleID > 0 && startDate != null && endDate != null)
                {
                    UserAssignRoleDB _userAssignRoleDB = new UserAssignRoleDB()
                    {
                        UserID=userID,
                        UserRoleID=roleID,
                        StartDate=startDate,
                        EndDate=endDate,
                        Active=true
                    };

                    _userAssignRoleDB = _userManagerData.AddNewUserRole(_userAssignRoleDB);

                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public bool RemoveUserRole(int userID, int roleID)
        {
            try 
            {
                if (userID > 0 && roleID > 0)
                {

                    return _userManagerData.RemoveUserRole(userID, roleID); ;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public IList<User> FindAllActiveUsers()
        {
            try
            {
                return FindUserList(_userManagerData.FindAllActiveUsers());
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IList<User> FindAllInactiveUsers()
        {
            try
            {
                return FindUserList(_userManagerData.FindAllInactiveUsers());
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public User FindUserByID(int userID)
        {
            try
            {
                return FindUser(_userManagerData.FindUserByID(userID));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public User FindUserByUserName(string userName)
        {
            try
            {
                return FindUser(_userManagerData.FindUserByUserName(userName));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IList<User> FindUserByFirstName(string firstName)
        {
            try
            {
                return FindUserList(_userManagerData.FindUserByFirstName(firstName));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public User ValidateLogInUser(string userName, string password)
        {
            try
            {
                User user = FindUser(_userManagerData.FindUserByUserName(userName));

                if (user == null)
                {

                    User invalidUser = new User()
                    {
                        ValidationResult = new UserValidationPresenter() { IsValidUser = false, ExceptionMessage = "Invalid Username." }
                    };

                    return invalidUser;
                }
                else if (password == user.Password)
                {
                    return user;
                }
                else
                {
                    User invalidUser = new User()
                    {
                        ValidationResult = new UserValidationPresenter() { IsValidUser = false, ExceptionMessage = "Invalid Password." }
                    };

                    return invalidUser;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private IList<User> FindUserList(IList<UserDB> userDBList)
        {
            try
            {
                IList<User> userList = new List<User>();
                foreach (UserDB userDB in userDBList)
                {
                    IList<UserAssignRole> userAssignRoleList = _roleManager.FindUserAssignRoleByUserID(userDB.ID);
                    User user = new User()
                    {
                        UserID = userDB.ID,
                        FirstName = userDB.FirstName,
                        MiddleName = userDB.MiddleName,
                        LastName = userDB.LastName,
                        Email = userDB.Email,
                        UserName = userDB.UserName,
                        Password = userDB.Password,
                        Role = userAssignRoleList,
                        ValidationResult = new UserValidationPresenter() { IsValidUser=true,ExceptionMessage=""}
                    };
                    userList.Add(user);
                }
                return userList;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private User FindUser(UserDB userDB)
        {
            try
            {
                if (userDB == null)
                {
                    return null;
                }
                else
                {
                    IList<UserAssignRole> userAssignRoleList = _roleManager.FindUserAssignRoleByUserID(userDB.ID);
                    User user = new User()
                    {
                        UserID = userDB.ID,
                        FirstName = userDB.FirstName,
                        MiddleName = userDB.MiddleName,
                        LastName = userDB.LastName,
                        Email = userDB.Email,
                        UserName = userDB.UserName,
                        Password = userDB.Password,
                        Role = userAssignRoleList,
                        ValidationResult = new UserValidationPresenter() { IsValidUser = true, ExceptionMessage = "" }
                    };
                    return user;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    }
}
